package com.roamer.audition.server.repository.base;

import com.roamer.audition.server.entity.base.LogicDeleteBaseEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

/**
 * 自定义JPA BaseFactoryBean
 *
 * @author roamer
 * @version V1.0
 * @date 2019/9/5 10:14 上午
 */
public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, I> {

    /**
     * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface.
     *
     * @param repositoryInterface must not be {@literal null}.
     */
    public BaseRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
        super(repositoryInterface);
    }

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(final EntityManager entityManager) {
        return new JpaRepositoryFactory(entityManager) {

            @Override
            protected SimpleJpaRepository<T, I> getTargetRepository(RepositoryInformation information,
                                                                    EntityManager entityManager) {
                Class<T> domainClass = (Class<T>) information.getDomainType();
                if (LogicDeleteBaseEntity.class.isAssignableFrom(domainClass)) {
                    return new LogicDeleteRepositoryImpl(domainClass, entityManager);
                } else {
                    return new SimpleJpaRepository<>(domainClass, entityManager);
                }
            }

            @Override
            protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
                return LogicDeleteBaseEntity.class.isAssignableFrom(
                        metadata.getDomainType()) ? LogicDeleteRepositoryImpl.class : SimpleJpaRepository.class;
            }
        };
    }
}
